package com.aegis.core.utils;

import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.aegis.core.constants.AegisTokenRedisConstants;
import com.aegis.core.manager.AegisAppManager;
import com.aegis.core.manager.AegisDataCleanManager;
import com.aegis.core.manager.AegisUserPermissionManager;
import com.aegis.core.model.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author wuweixin
 *
 * @Version 1.0
 * @Descritube 将core的核心功能都封装到util，开发者主要调用这个工具类即可
 */
public class AegisUserUtil {

    private AegisUserUtil() {
        throw new IllegalStateException("Utility class");
    }

    /**
     * 登入
     *
     * @param userId
     * @return
     */
    public static AegisLoginInfo login(String userId, String account) {
        AegisSession aegisSession = new AegisSession();
        aegisSession.setAccount(account);
        aegisSession.setUserId(userId);
        return login(aegisSession);
    }

    /**
     * 登入
     *
     * @param aegisSession
     * @return
     */
    public static AegisLoginInfo login(AegisSession aegisSession) {
        validateParams(aegisSession);
        fillUserInfo(aegisSession);
        StpUtil.login(aegisSession.getUserId());
        setCurrentUserSession(aegisSession);
        AegisDataCleanManager.setLoginUser(aegisSession.getAppId(), aegisSession.getUserId(), aegisSession);
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        return new AegisLoginInfo(tokenInfo);
    }

    /**
     * 添加应用分组的权限（使用当前应用ID）
     *
     * @param groupPermissions 需要追加的权限组配置列表
     */
    public static void addGroupPermission(List<AegisAppGroupPermission> groupPermissions) {
        addGroupPermission(AegisAppManager.getAppId(), groupPermissions);
    }

    /**
     * 清空应用权限组（使用当前应用ID）
     */
    public static void clearGroupPermission() {
        clearGroupPermission(AegisAppManager.getAppId());
    }


    /**
     * 添奖应用分组的权限，即RBAC模型中，角色(group)可以访问哪些api
     *
     * @param appId
     * @param groupPermissions
     */
    public static void addGroupPermission(String appId, List<AegisAppGroupPermission> groupPermissions) {
        AegisUserPermissionManager.addGroupPermission(appId, groupPermissions);
    }

    /**
     * 清空应用权限组
     *
     * @param appId
     */
    public static void clearGroupPermission(String appId) {
        AegisUserPermissionManager.clearGroupPermission(appId);
    }


    /**
     * 设置用户允许访问的api地址（使用当前应用ID）
     */
    public static void setUserAllowApiPermission(Object userId, List<AegisUserApi> allowApi) {
        setUserAllowApiPermission(AegisAppManager.getAppId(), userId, allowApi);
    }

    /**
     * 设置用户禁止api访问权限（使用当前应用ID）
     */
    public static void setUserRejectApiPermission(Object userId, List<AegisUserApi> rejectApi) {
        setUserRejectApiPermission(AegisAppManager.getAppId(), userId, rejectApi);
    }

    /**
     * 添加用户允许访问的api接口（使用当前应用ID）
     */
    public static void addUserAllowApiPermission(Object userId, List<AegisUserApi> allowApi) {
        addUserAllowApiPermission(AegisAppManager.getAppId(), userId, allowApi);
    }

    /**
     * 添加用户禁止访问的api接口（使用当前应用ID）
     */
    public static void addRejectApiPermission(Object userId, List<AegisUserApi> rejectApi) {
        addRejectApiPermission(AegisAppManager.getAppId(), userId, rejectApi);
    }

    /**
     * 清空用户允许访问的API接口（使用当前应用ID）
     */
    public static void clearUserAllowApi(Object userId) {
        clearUserAllowApi(AegisAppManager.getAppId(), userId);
    }

    /**
     * 清空用户被禁止访问的API接口（使用当前应用ID）
     */
    public static void clearUserRejectApi(Object userId) {
        clearUserRejectApi(AegisAppManager.getAppId(), userId);
    }

    /**
     * 获取用户权限（使用当前应用ID）
     */
    public static AegisUserPermission getUserPermission(Object userId) {
        return getUserPermission(AegisAppManager.getAppId(), userId);
    }

    /**
     * 添加用户组别（使用当前应用ID）
     */
    public static void addUserGroup(Object userId, List<String> groupKeys) {
        addUserGroup(AegisAppManager.getAppId(), userId, groupKeys);
    }

    /**
     * 设置用户组别（使用当前应用ID）
     */
    public static void setUserGroup(Object userId, List<String> groupKeys) {
        setUserGroup(AegisAppManager.getAppId(), userId, groupKeys);
    }

    /**
     * 清空用户组别（使用当前应用ID）
     */
    public static void clearUserGroup(String appId, Object userId) {
        AegisUserPermissionManager.clearUserGroup(appId, userId);
    }

    /**
     * 获取用户总权限（使用当前应用ID）
     */
    public static AegisUserTotalPermission getUserTotalPermission(Object userId) {
        return getUserTotalPermission(AegisAppManager.getAppId(), userId);
    }


    /**
     * 设置用户允许访问的api地址，会替换原有的地址
     *
     * @param allowApi
     */
    public static void setUserAllowApiPermission(String appId, Object userId, List<AegisUserApi> allowApi) {
        AegisUserPermissionManager.setUserAllowApiPermission(appId, userId, allowApi);
    }

    /**
     * 设置用户禁止api访问权限，会替换原有的权限
     * 如果某个用户被分到某个api权限组，但是想禁止这个用户访问某些api，又不想为这个用户再单独开一个权限组，可以单独禁止这个用户访问某些api
     *
     * @param userId
     * @param rejectApi
     */
    public static void setUserRejectApiPermission(String appId, Object userId, List<AegisUserApi> rejectApi) {
        AegisUserPermissionManager.setUserRejectApiPermission(appId, userId, rejectApi);
    }

    /**
     * 添加用户允许访问的api接口
     *
     * @param allowApi
     */
    public static void addUserAllowApiPermission(String appId, Object userId, List<AegisUserApi> allowApi) {
        AegisUserPermissionManager.addUserAllowApiPermission(appId, userId, allowApi);
    }

    /**
     * 添加用户禁止访问的api接口
     *
     * @param rejectApi
     */
    public static void addRejectApiPermission(String appId, Object userId, List<AegisUserApi> rejectApi) {
        AegisUserPermissionManager.addUserRejectApiPermission(appId, userId, rejectApi);
    }


    /**
     * 清空用户允许访问的API接口
     *
     * @param userId
     */
    public static void clearUserAllowApi(String appId, Object userId) {
        AegisUserPermissionManager.clearUserAllowApi(appId, userId);
    }

    /**
     * 清空用户被禁止访问的API接口
     *
     * @param userId
     */
    public static void clearUserRejectApi(String appId, Object userId) {
        AegisUserPermissionManager.clearUserRejectApi(appId, userId);
    }

    /**
     * @param userId
     * @return
     */
    public static AegisUserPermission getUserPermission(String appId, Object userId) {
        return AegisUserPermissionManager.getUserPermission(appId, userId);
    }

    /**
     * 添加用户的组别
     *
     * @param userId
     * @param groupKeys
     */
    public static void addUserGroup(String appId, Object userId, List<String> groupKeys) {
        AegisUserPermissionManager.addUserGroup(appId, userId, groupKeys);
    }

    /**
     * 设置用户的组别
     *
     * @param userId
     * @param groupKeys
     */
    public static void setUserGroup(String appId, Object userId, List<String> groupKeys) {
        AegisUserPermissionManager.setUserGroup(appId, userId, groupKeys);
    }

    /**
     * 清空用户的组别
     *
     * @param userId
     */
    public static void clearUserGroup(Object userId) {
        AegisUserPermissionManager.clearUserGroup(AegisAppManager.getAppId(), userId);
    }


    /**
     * 获取当前登录的用户信息
     *
     * @return
     */
    public static AegisSession getLoginUserInfo() {
        return getLoginUserInfo(StpUtil.getLoginId());
    }


    /**
     * 获取某个已登录的用户的信息
     *
     * @param userId
     * @return
     */
    public static AegisSession getLoginUserInfo(Object userId) {
        AegisSession result = null;
        SaSession sessionByLoginId = StpUtil.getSessionByLoginId(userId);
        result = (AegisSession) sessionByLoginId.get(AegisTokenRedisConstants.getUserInfoRedisKey(userId));
        if (result != null) {
            return result;
        }
        return result;
    }


    /**
     * 获取当前用户的id
     *
     * @return
     */
    public static Object getLoginUserId() {
        try {
            return StpUtil.getLoginIdDefaultNull();
        } catch (Exception e) {
//            AegisLogUtil.error("获取当前用户id失败", e);
        }
        return null;
    }


    /**
     * 设置当前用户的session信息
     *
     * @param aegisSession
     */
    public static void setCurrentUserSession(AegisSession aegisSession) {
        SaSession session = StpUtil.getSession();
        session.set(AegisTokenRedisConstants.getUserInfoRedisKey(aegisSession.getUserId()), aegisSession);
    }

    /**
     * 设置当前用户的session信息
     *
     * @param aegisSession
     */
    public static void setUserSession(AegisSession aegisSession) {
        SaSession session = StpUtil.getSession();
        session.set(AegisTokenRedisConstants.getUserInfoRedisKey(aegisSession.getUserId()), aegisSession);
    }

    /**
     * 当前用户登出
     */
    public static void logout() {
        logout(getToken());
    }

    /**
     * 登出
     *
     * @param token
     */
    public static void logout(String token) {
        StpUtil.logoutByTokenValue(token);
    }


    /**
     * 获取当前登录的用户token
     *
     * @return
     */
    public static String getToken() {
        return StpUtil.getTokenValue();
    }


    /**
     * 获得用户总的权限，即返回用户所在权限组的权限 + 用户本身的权限
     *
     * @param appId
     * @param userId
     * @return
     */
    public static AegisUserTotalPermission getUserTotalPermission(String appId, Object userId) {
        AegisUserPermission userPermission = getUserPermission(appId, userId);
        if (userPermission == null) {
            return null;
        }
        AegisUserTotalPermission aegisUserTotalPermission = new AegisUserTotalPermission();
        aegisUserTotalPermission.setAppId(appId);
        aegisUserTotalPermission.setUserId(userId);
        List<AegisUserApi> allowApi = userPermission.getAllowApi();
        List<AegisUserApi> rejectApi = userPermission.getRejectApi();
        aegisUserTotalPermission.setRejectApi(rejectApi);
        aegisUserTotalPermission.setAllowApi(allowApi);
        if (!AegisCommonUtil.isCollectionEmpty(userPermission.getGroup())) {
            List<AegisAppGroupPermission> appGroup = AegisUserPermissionManager.getAppGroup(appId, userPermission.getGroup()
                    .toArray(new String[0]));
            aegisUserTotalPermission.setGroupPermissions(appGroup.stream()
                    .filter(aegisAppGroupPermission -> userPermission.getGroup()
                            .contains(aegisAppGroupPermission.getGroupKey())).collect(Collectors.toList()));
        }
        return aegisUserTotalPermission;
    }


    /**
     * @param aegisSession
     */
    private static void validateParams(AegisSession aegisSession) {
        if (aegisSession.getUserId() == null) {
            throw new IllegalArgumentException("缺少用户id");
        }
        if (AegisCommonUtil.isStringBlank(aegisSession.getAccount())) {
            throw new IllegalArgumentException("缺少账户信息");
        }
        if (AegisCommonUtil.isStringBlank(aegisSession.getAppId())) {
            throw new IllegalArgumentException("缺少应用id");
        }
        AegisAppManager.checkAppExisting(aegisSession.getAppId());

    }

    /**
     * @param aegisSession
     */
    private static void fillUserInfo(AegisSession aegisSession) {
        aegisSession.setCreateTime(new Date());
        aegisSession.setLoginDevice(StpUtil.getLoginDevice());
        aegisSession.setLoginIp(AegisCommonUtil.getClientIp());
    }


}
